/**
 * 
 */
package gsoc.ogsadai.custom.actions;


import gsoc.ogsadai.client.ServerClient;
import gsoc.ogsadai.custom.Activator;
import gsoc.ogsadai.model.diagram.edit.parts.WorkflowTypeEditPart;
import gsoc.ogsadai.model.diagram.part.ValidateAction;
import gsoc.ogsadai.model.properties.PropertiesStyle;
import gsoc.ogsadai.model.util.ModelResourceImpl;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.validation.model.IConstraintStatus;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.dialogs.ListDialog;

import uk.org.ogsadai.client.toolkit.RequestResource;

/**
 * @author Nicola Salvo
 * 9 Jul 2008
 */
public class DeployWorkflowAction implements IObjectActionDelegate {

	private WorkflowTypeEditPart mySelectedElement;
	 private Text text;
	 private IWorkbenchPart editor;
	 
	public static final String ID = "gsoc.ogsadai.diagram.popup.deployWorkflowID";
	/* (non-Javadoc)
	 * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction, org.eclipse.ui.IWorkbenchPart)
	 */
	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
		editor = targetPart;
	}
	
	 /**
	  * This method Validates the in memory representation of the model and if it's
	  * valid, saves a copy of the model on the tmp directory and call the 
	  * executeRequest(fileName) to execute the request. 
	  * 
	  * The commented code use a custom validator, but to until it's not ready and complete
	  * it's more advisable to use the validator provided by EMF it self.
	  * 
	  * 
	  */
	/* (non-Javadoc)
	 * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
	 */
	/* (non-Javadoc)
	 * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
	 */
	public void run(IAction action) {
		
		ResourceSet resourceSet = mySelectedElement.getEditingDomain().getResourceSet();// getEditingDomain().getResourceSet();
		View view = (View)mySelectedElement.getModel();
		List styleList = view.getStyles();
		PropertiesStyle style = null;
		
		String serverURL = "";
		String fileName = "/tmp/default.xml";
	
		//ValidationDelegateClientSelector.running = true;

		
		Shell shell = editor.getSite().getShell();
/*		IBatchValidator validator = (IBatchValidator)ModelValidationService.getInstance()
			.newValidator(EvaluationMode.BATCH);
		validator.setIncludeLiveConstraints(true);
		
		final IStatus status = validator.validate(view.getElement());				

		System.out.println("Validating " + view.getElement());
		
		ValidationDelegateClientSelector.running = false;

		Diagnostic diagnostic =new Diagnostician() {

			public String getObjectLabel(EObject eObject) {
				return EMFCoreUtil.getQualifiedName(eObject, true);
			}
		}.validate(view.getElement());
	
					

		if (status.isOK()) {
			MessageDialog.openInformation(shell, "COOL",
					"validation successful");
			return;
		} else {
			ListDialog dialog = new ListDialog(shell);
			dialog.setInput(status);
			dialog.setTitle("BOOO");
			dialog.setContentProvider(new IStructuredContentProvider() {
				public void dispose() {
					// nothing to dispose
				}

				public Object[] getElements(Object inputElement) {
					if (status != null && status.isMultiStatus()
							&& status == inputElement) {
						return status.getChildren();
					} else if (status != null && status == inputElement) {
						return new Object[] { status };
					}
					return new Object[0];
				}

				public void inputChanged(Viewer viewer, Object oldInput,
						Object newInput) {
					// Do nothing.
				}
			});
			dialog.setLabelProvider(new LabelProvider() {
				public String getText(Object element) {
					if (element instanceof IStatus) {
						return ((IStatus) element).getMessage();
					}
					return null;
				}
			});
			dialog.setBlockOnOpen(true);
			dialog.setMessage("Errors during validation");

			if (ListDialog.OK == dialog.open()) {
				Set<EObject> errorSelections = new HashSet<EObject>();
				if (!status.isMultiStatus()) {
					IConstraintStatus cstatus = (IConstraintStatus) status;
					errorSelections.add(cstatus.getTarget());
				} else {
					IStatus[] children = status.getChildren();
					for (int i = 0; i < children.length; i++) {
						IConstraintStatus cstatus = (IConstraintStatus) children[i];
						errorSelections.add(cstatus.getTarget());
					}
				}
				//editorPart. .setSelectionToViewer(errorSelections);
			}
		}


		// Create problem markers on the resources with validation
		// failures/warnings.
		try {
			MarkerUtil.createMarkers(status);
		} catch (CoreException e) {
			Activator.getDefault().getLog().log(e.getStatus());
		}
		
*/	
		
		
		final IStatus status = ValidateAction.runValidation(mySelectedElement.getDiagramView());
		if (status.isOK()) {
			MessageDialog.openInformation(shell, "COOL",
					"validation successful");
			
		}  else {
			ListDialog dialog = new ListDialog(shell);
			dialog.setInput(status);
			dialog.setTitle("Error");
			dialog.setContentProvider(new IStructuredContentProvider() {
				public void dispose() {
					// nothing to dispose
				}

				public Object[] getElements(Object inputElement) {
					if (status != null && status.isMultiStatus()
							&& status == inputElement) {
						return status.getChildren();
					} else if (status != null && status == inputElement) {
						return new Object[] { status };
					}
					return new Object[0];
				}

				public void inputChanged(Viewer viewer, Object oldInput,
						Object newInput) {
					// Do nothing.
				}
			});
			dialog.setLabelProvider(new LabelProvider() {
				public String getText(Object element) {
					if (element instanceof IStatus) {
						return ((IStatus) element).getMessage();
					}
					return null;
				}
			});
			dialog.setBlockOnOpen(true);
			dialog.setMessage("Errors during validation");

			if (ListDialog.OK == dialog.open()) {
				Set<EObject> errorSelections = new HashSet<EObject>();
				if (!status.isMultiStatus()) {
					IConstraintStatus cstatus = (IConstraintStatus) status;
					errorSelections.add(cstatus.getTarget());
				} else {
					IStatus[] children = status.getChildren();
					for (int i = 0; i < children.length; i++) {
						IConstraintStatus cstatus = (IConstraintStatus) children[i];
						errorSelections.add(cstatus.getTarget());
					}
				}
				//editorPart. .setSelectionToViewer(errorSelections);
			}
			return;
		}
		for (Object obj : styleList) {
			if (obj instanceof PropertiesStyle)				
				style = (PropertiesStyle) obj;			
		}
		/**
		 * TODO How does it work on windows? Check it!!!
		 */
		if(style != null){
			fileName = "/tmp/"+EcoreUtil.getURI((EObject)style).fragment()+".xml";			
			serverURL = style.getServerURL();			
		}
		/**
		 * TODO This serialization is really inefficient. The proper way is to use this code:
		 *		  	
		    documentBuilder = documentBuilderFactory.newDocumentBuilder();
			
			Document document = documentBuilder.newDocument();
			

			for(Resource resource: resourceSet.getResources()){		
				if(resource instanceof ModelResourceImpl){
					((XMLResource)resource).save (document, null, null);
					break:
				}
			}
			DocumentClient   clientDoc = new DocumentClient();
			DocumentWorkflow workflowDoc =  clientDoc.executeRequest(document,serverURL);
			
		* The problem with this is that there is a conflict between the xerces
		* libraries used by OGSA-DAI and EMF.
		*/
			   
		try {
			
			FileOutputStream fos = new FileOutputStream(new File(fileName));
			for(Resource resource: resourceSet.getResources()){		
				if(resource instanceof ModelResourceImpl)		
					resource.save(fos,null);
			}
			
			ServerClient server= new ServerClient(serverURL);			
			RequestResource request =  server.executeRequest(fileName);
			Activator.getDefault().getRequestResourceList().add(request);		
		    
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
						

		
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
	 */
		

	
	
	public void selectionChanged(IAction action, ISelection selection) {
		mySelectedElement = null;
		if (selection instanceof IStructuredSelection) {
			IStructuredSelection structuredSelection = (IStructuredSelection) selection;
			if (structuredSelection.size() == 1
					&& structuredSelection.getFirstElement() instanceof WorkflowTypeEditPart) {
				mySelectedElement = (WorkflowTypeEditPart) structuredSelection
						.getFirstElement();
			}
		}
		action.setEnabled(isEnabled());
	}

	
	private boolean isEnabled() {
		return mySelectedElement != null;
	}
}
